package de.tum.in.eist.im.server;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.sun.jmx.remote.internal.ClientListenerInfo;

import de.tum.in.eist.im.client.ChatServiceNew;
import de.tum.in.eist.im.client.domain.Message;
import de.tum.in.eist.im.client.domain.NewMessagesChunk;
import de.tum.in.eist.im.client.domain.User;

public class ChatServiceNewImpl extends RemoteServiceServlet implements ChatServiceNew 
{
    /**
     * 
     */
    private static final long serialVersionUID = 2677792196507651579L;
    private ArrayList<User> knownUsers;
    private ArrayList<User> loggedInUsers;
    
    private HashMap <Long, Message> chatHistory;
    private HashMap <User, Long> lifeSigns;
    
    public ChatServiceNewImpl ()
    {
        knownUsers = new ArrayList <User> ();
        loggedInUsers = new ArrayList <User> ();
        chatHistory = new HashMap <Long, Message> ();
        lifeSigns = new HashMap <User, Long> ();
    }

    @Override
    public NewMessagesChunk getNewMessages (long clientLastTimestamp)
    {
        ArrayList <Message> msgs = new ArrayList <Message> ();
        NewMessagesChunk res = new NewMessagesChunk();
        res.setTimestamp(new Date().getTime());
        //Get sorted list of keys, aka message timestamps,
        TreeSet<Long> stamps = new TreeSet<Long>(chatHistory.keySet());
        for (long l : stamps.tailSet(clientLastTimestamp))
        {
        	msgs.add(chatHistory.get(l));
        }
        
        res.setMessages (msgs);
        
        return res;
    }

    @Override
    public void sendMessage (Message message)
    {
    	//Use servertime stamp of arrival as key to make up for latency
    	chatHistory.put((new Date()).getTime(), message);
       //chatHistory.put (message.getTimestamp (), message);
    }

    @Override
    public boolean login (User user)
    {
        // search for user
        for (User u : knownUsers)
        {
            if (u.getUsername ().equals (user.getUsername ()))
            {
                // user found, check for existing account
                for (User u2 : loggedInUsers)
                {
                    if (u2.getUsername ().equals (user.getUsername ()))
                    {
                        return false;
                    }
                }
                
                // not logged in, check password
                if (u.getPassword ().equals (user.getPassword ()))
                {
                    loggedInUsers.add (user);
                    lifeSigns.put (u, new Date ().getTime ());
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        
        return false;
    }

    @Override
    public boolean logout (User user)
    {
        loggedInUsers.remove (user);
        lifeSigns.remove (user);
        return true;
    }

    @Override
    public void registerNewUser (User newUser)
    {
        // search user
        for (User u : knownUsers)
        {
            if (u.getUsername ().equals (newUser.getUsername ()))
            {
                // user already exists
                return;
            }
        }
        
        knownUsers.add (newUser);
    }

    @Override
    public List <User> getLoggedInUsers ()
    {
        return loggedInUsers;
    }

    @Override
    public List <Message> getHistory (Date from)
    {
        return getNewMessages(from.getTime ()).getMessages ();
    }

}
